package com.stars.easyms.monitor.system;

import com.stars.easyms.monitor.MonitorRequestHandler;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.text.NumberFormat;
import java.util.*;

/**
 * <p>className: EasyMsGitMonitorRequestHandler</p>
 * <p>description: EasyMsGit版本监控请求处理类</p>
 *
 * @author guoguifang
 * @date 2019/11/26 14:59
 * @since 1.4.1
 */
public final class EasyMsSystemMonitorRequestHandler implements MonitorRequestHandler {

    private static final int GB = 1073741824;

    private static final int MB = 1048576;

    private static final int KB = 1024;

    private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance();

    @Override
    public Map<String, Object> getMonitorInfo() {
        Runtime runtime = Runtime.getRuntime();

        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();

        long physicalMemory;
        try {
            physicalMemory = ((com.sun.management.OperatingSystemMXBean) ManagementFactory
                    .getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
        } catch (Exception e) {
            physicalMemory = -1L;
        }

        int availableCores = Runtime.getRuntime().availableProcessors();

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("Java version", System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
        result.put("Operating system", System.getProperty("os.name") + " " + System.getProperty("os.version"));
        result.put("File Encoding", System.getProperty("file.encoding"));
        result.put("CPU Cores", availableCores);
        if (physicalMemory != -1L) {
            result.put("Physical Memory", parseFromByteSize(physicalMemory));
        }
        result.put("Max allowed memory", parseFromByteSize(maxMemory));
        result.put("Allocated memory", parseFromByteSize(allocatedMemory));
        result.put("Used memory in allocated", parseFromByteSize((allocatedMemory - freeMemory)));
        result.put("Free memory in allocated", parseFromByteSize(freeMemory));
        result.put("Total free memory", parseFromByteSize((freeMemory + (maxMemory - allocatedMemory))));

        MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapMemoryUsage = memoryMxBean.getHeapMemoryUsage();
        Map<String, Object> heapMemoryUsageMap = new LinkedHashMap<>();
        heapMemoryUsageMap.put("init", parseFromByteSize(heapMemoryUsage.getInit()));
        heapMemoryUsageMap.put("used", parseFromByteSize(heapMemoryUsage.getUsed()));
        heapMemoryUsageMap.put("committed", parseFromByteSize(heapMemoryUsage.getCommitted()));
        heapMemoryUsageMap.put("max", parseFromByteSize(heapMemoryUsage.getMax()));
        result.put("Heap Memory Usage", heapMemoryUsageMap);

        MemoryUsage nonHeapMemoryUsage = memoryMxBean.getNonHeapMemoryUsage();
        Map<String, Object> nonHeapMemoryUsageMap = new LinkedHashMap<>();
        nonHeapMemoryUsageMap.put("init", parseFromByteSize(nonHeapMemoryUsage.getInit()));
        nonHeapMemoryUsageMap.put("used", parseFromByteSize(nonHeapMemoryUsage.getUsed()));
        nonHeapMemoryUsageMap.put("committed", parseFromByteSize(nonHeapMemoryUsage.getCommitted()));
        nonHeapMemoryUsageMap.put("max", parseFromByteSize(nonHeapMemoryUsage.getMax()));
        result.put("Non-Heap Memory Usage", nonHeapMemoryUsageMap);
        return result;
    }

    @Override
    public int getOrder() {
        return -20;
    }

    @Override
    public String getModuleName() {
        return "system";
    }

    private String parseFromByteSize(long byteSize) {
        if (byteSize <= 0) {
            return String.valueOf(byteSize);
        }
        long gb = byteSize >> 30;
        if (byteSize - gb * GB == 0 || gb > 100) {
            return NUMBER_FORMAT.format(gb) + " GB";
        }
        long mb = byteSize >> 20;
        if (byteSize - mb * MB == 0 || mb > 100) {
            return NUMBER_FORMAT.format(mb) + " MB";
        }
        long kb = byteSize >> 10;
        if (byteSize - kb * KB == 0 || kb > 100) {
            return NUMBER_FORMAT.format(kb) + " KB";
        }
        return NUMBER_FORMAT.format(byteSize) + " B";
    }

}
